home *** CD-ROM | disk | FTP | other *** search
/ Whiteline: delta / whiteline CD Series - delta.iso / progtool / c / egem_210 / egem / source / popup.c < prev    next >
C/C++ Source or Header  |  1995-11-25  |  8KB  |  406 lines

  1.  
  2. #include "proto.h"
  3. #include <string.h>
  4.  
  5. static int        ob_next(OBJECT *,int);
  6. static int         ob_find(OBJECT *,int,int);
  7. static int        do_popup(OBJECT *,boolean,int,int *);
  8.  
  9. #ifdef DEBUG
  10. extern void _check_hotkeys(OBJECT *);
  11. #endif
  12.  
  13. static int ob_check(OBJECT *obj)
  14. {
  15.     return ((obj->ob_state & DISABLED)==0 && (obj->ob_flags & (SELECTABLE|HIDETREE))==SELECTABLE);
  16. }
  17.  
  18. static int ob_search(OBJECT *tree,int last)
  19. {
  20.     reg int j;
  21.  
  22.     for (j=tree->ob_head;j<=last;j++)
  23.         if (ob_check(&tree[j]))
  24.             return (j);
  25.  
  26.     return (FAIL);
  27. }
  28.  
  29. static int ob_next(OBJECT *tree,int start)
  30. {
  31.     reg OBJECT *obj;
  32.     reg int i = start;
  33.  
  34.     if (start<tree->ob_head)
  35.         start = tree->ob_head;
  36.  
  37.     do
  38.     {
  39.         obj = tree + i;
  40.         if (ob_check(&tree[i]))
  41.             return(i);
  42.         i = obj->ob_next;
  43.     }
  44.     while (i>=0);
  45.  
  46.     return(FAIL);
  47. }
  48.  
  49. static int ob_find(OBJECT *tree,int x,int y)
  50. {
  51.     reg int pos = objc_find(tree,ROOT,1,x,y);
  52.  
  53.     if (pos>0 && ob_next(tree,pos)==pos)
  54.         return(pos);
  55.     else
  56.         return(FAIL);
  57. }
  58.  
  59. static int do_popup(OBJECT *menu,boolean wrap,int last,int *dc)
  60. {
  61.     reg int current,old = FAIL,ret = FAIL;
  62.     XEVENT events;
  63.  
  64.     _mouse_pos(&events.ev_mmox,&events.ev_mmoy);
  65.     if ((current = ob_find(menu,events.ev_mmox,events.ev_mmoy))<=0)
  66.         current = last;
  67.  
  68.     memset(&events,0,sizeof(XEVENT));
  69.     events.ev_mflags = MU_BUTTON|MU_M1|MU_KEYBD;
  70.     events.ev_mbstate = events.ev_mbclicks = events.ev_bmask = 1;
  71.  
  72.     for (;;)
  73.     {
  74.         if (current!=old)
  75.         {
  76.             if (old>0)
  77.                 ob_select(NULL,menu,old,CLEAR_STATE,TRUE);
  78.  
  79.             if (current>0)
  80.                 ob_select(NULL,menu,current,SET_STATE,TRUE);
  81.  
  82.             old = current;
  83.         }
  84.  
  85.         if (objc_find(menu,ROOT,1,events.ev_mmox,events.ev_mmoy)<0)
  86.         {
  87.             events.ev_mm1flags = 0;
  88.             *(GRECT *) &events.ev_mm1x = *(GRECT *) &menu->ob_x;
  89.         }
  90.         else
  91.         {
  92.             events.ev_mm1flags = events.ev_mm1width = events.ev_mm1height = 1;
  93.             events.ev_mm1x = events.ev_mmox;
  94.             events.ev_mm1y = events.ev_mmoy;
  95.         }
  96.  
  97.         Event_Multi(&events);
  98.         if (events.ev_mwich & MU_BUTTON)
  99.         {
  100.             if (!(events.ev_mmobutton & 1))
  101.             {
  102.                 ret = ob_find(menu,events.ev_mmox,events.ev_mmoy);
  103.                 break;
  104.             }
  105.             else
  106.                 events.ev_mbstate = 0;
  107.         }
  108.  
  109.         if (events.ev_mwich & MU_M1)
  110.         {
  111.             current = ob_find(menu,events.ev_mmox,events.ev_mmoy);
  112.             events.ev_mm2x = events.ev_mmox;
  113.             events.ev_mm2y = events.ev_mmoy;
  114.         }
  115.  
  116.         if (events.ev_mwich & MU_KEYBD)
  117.         {
  118.             int exitmode = FALSE;
  119.  
  120.             switch (events.ev_mkreturn & 0x00ff)
  121.             {
  122.             case 13:
  123.             case 32:
  124.                 ret = current;
  125.                 exitmode = TRUE;
  126.                 break;
  127.             case 27:
  128.                 ret = FAIL;
  129.                 exitmode = TRUE;
  130.             }
  131.  
  132.             if (exitmode==FALSE)
  133.             {
  134.                 switch (events.ev_mkreturn>>8)
  135.                 {
  136.                 case 97:
  137.                     ret = FAIL;
  138.                     exitmode = TRUE;
  139.                     break;
  140.                 case 71:
  141.                     if (events.ev_mmokstate & 3)
  142.                         current = ob_search(menu,menu->ob_tail);
  143.                     else
  144.                         current = ob_next(menu,menu->ob_head);
  145.                     break;
  146.                 case 75:
  147.                 case 72:
  148.                     {
  149.                         reg int temp = FAIL;
  150.  
  151.                         if (current>menu->ob_head)
  152.                             temp = ob_search(menu,current-1);
  153.  
  154.                         if (temp<0 && (wrap || current<0))
  155.                             temp = ob_search(menu,menu->ob_tail);
  156.  
  157.                         if (temp>0)
  158.                             current = temp;
  159.                     }
  160.                     break;
  161.                 case 77:
  162.                 case 80:
  163.                     if (current<menu->ob_tail)
  164.                     {
  165.                         if (current<0)
  166.                             current = ob_next(menu,menu->ob_head);
  167.                         else
  168.                         {
  169.                             int temp = ob_next(menu,menu[current].ob_next);
  170.                             if (temp>0 && temp!=current)
  171.                                 current = temp;
  172.                             else
  173.                                 current = ob_next(menu,menu->ob_head);
  174.                         }
  175.                     }
  176.                     else if (wrap)
  177.                         current = ob_next(menu,menu->ob_head);
  178.                     break;
  179.                 default:
  180.                     {
  181.                         int obj;
  182.     
  183.                         if ((obj=_is_hotkey(menu,scan_2_ascii(events.ev_mkreturn,events.ev_mmokstate)))>0)
  184.                         {
  185.                             if (ob_check(&menu[obj]))
  186.                             {
  187.                                 if (old>0)
  188.                                     ob_select(NULL,menu,old,CLEAR_STATE,TRUE);
  189.                                 ob_select(NULL,menu,obj,SET_STATE,TRUE);
  190.  
  191.                                 Event_Timer(100,0);
  192.     
  193.                                 exitmode = TRUE;
  194.                                 ret = obj;
  195.                             }
  196.                         }
  197.                     }
  198.                 }
  199.             }
  200.  
  201.             if (exitmode)
  202.                 break;
  203.         }
  204.     }
  205.  
  206.     if (ret>0)
  207.         *dc = (events.ev_mbreturn>=2 || (events.ev_mmokstate & 3));
  208.     return (ret);
  209. }
  210.  
  211. int Popup(POPUP *popup,int mode,int center,int x,int y,int *index,int select)
  212. {
  213.     reg DIAINFO *info = popup->p_info;
  214.     reg OBJECT *menu = popup->p_menu,*tree=(info!=NULL) ? info->di_tree : NULL;
  215.     reg int current = FAIL,exit = FAIL,object;
  216.     int dc = FALSE;
  217.  
  218.     MouseArrow();
  219.  
  220.     if (tree!=NULL)
  221.     {
  222.         object = (mode & POPUP_CYCLE) ? popup->p_cycle : popup->p_parent;
  223.         if (object>0)
  224.             ob_select(info,tree,object,SET_STATE,TRUE);
  225.     }
  226.  
  227.     {
  228.         reg int i;
  229.  
  230.         for (i=menu->ob_head;i<=menu->ob_tail;i++)
  231.         {
  232.             if (menu[i].ob_flags & SELECTABLE)
  233.                 menu[i].ob_state &= ~SELECTED;
  234.  
  235.             if (!(menu[i].ob_flags & HIDETREE))
  236.             {
  237.                 if (i==select)
  238.                 {
  239.                     if (mode & POPUP_CHECK)
  240.                         menu[i].ob_state |= CHECKED;
  241.                     if (current>=0)
  242.                         menu[current].ob_state &= ~CHECKED;
  243.                     current=i;
  244.                 }
  245.                 else if (menu[i].ob_state & CHECKED)
  246.                 {
  247.                     if (!(mode & POPUP_CHECK) || current>=0)
  248.                         menu[i].ob_state &= ~CHECKED;
  249.                     else
  250.                         current = i;
  251.                 }
  252.             }
  253.         }
  254.     }
  255.  
  256.     if (!(mode & POPUP_CYCLE))
  257.     {
  258.         int sx,sy,sw = menu->ob_width>>1,sh = menu->ob_height>>1,dummy;
  259.         RC_RECT area;
  260.  
  261.         _mouse_pos(&sx,&sy);
  262.         if (tree!=NULL && popup->p_button>0)
  263.         {
  264.             int bx,by;
  265.             objc_offset(tree,popup->p_button,&bx,&by);
  266.             if (x<=0)
  267.                 x = bx;
  268.             if (y<=0)
  269.                 y = by;
  270.         }
  271.  
  272.         switch (center)
  273.         {
  274.         case CENTER:
  275.             {
  276.                 INFOVSCR *vscr;
  277.  
  278.                 form_center(menu,&dummy,&dummy,&dummy,&dummy);
  279.                 if (get_cookie(COOKIE_VSCR,(long *) &vscr) && (vscr->cookie==COOKIE_XBRA))
  280.                 {
  281.                     menu->ob_x = vscr->x + (vscr->w>>1) - sw;
  282.                     menu->ob_y = vscr->y + (vscr->h>>1) - sh;
  283.                 }
  284.             }
  285.             break;
  286.         case XYPOS:
  287.             menu->ob_x = x;
  288.             menu->ob_y = y;
  289.             break;
  290.         case MOUSEPOS:
  291.             menu->ob_x = sx - sw;
  292.             menu->ob_y = sy - sh;
  293.             break;
  294.         case XPOS:
  295.             menu->ob_x = x;
  296.             menu->ob_y = sy - sh;
  297.             break;
  298.         case YPOS:
  299.             menu->ob_x = sx - sw;
  300.             menu->ob_y = y;
  301.             break;
  302.         case OBJPOS:
  303.             menu->ob_x = x;
  304.             menu->ob_y = y;
  305.             if (current>=0)
  306.             {
  307.                 menu->ob_x -= menu[current].ob_x;
  308.                 menu->ob_y -= menu[current].ob_y;
  309.             }
  310.         }
  311.  
  312.         Min(&menu->ob_x,clip.v_x2 - menu->ob_width - 3);
  313.         Max(&menu->ob_x,clip.v_x1 + 3);
  314.         Min(&menu->ob_y,clip.v_y2 - menu->ob_height - 3);
  315.         Max(&menu->ob_y,clip.v_y1 + 3);
  316.  
  317.         sx = menu->ob_x - 3;
  318.         sy = menu->ob_y - 3;
  319.         sw = menu->ob_width + 6;
  320.         sh = menu->ob_height + 6;
  321.  
  322.         _popup++;
  323.         _beg_ctrl();
  324.  
  325.         _rc_sc_savetree(menu,&area);
  326.         if (!area.valid)
  327.             form_dial(FMD_START,0,0,0,0,sx,sy,sw,sh);
  328.         objc_draw(menu,ROOT,MAX_DEPTH,sx,sy,sw,sh);
  329.  
  330.     #ifdef DEBUG
  331.         check_hotkeys(menu);
  332.     #endif
  333.  
  334.         exit = do_popup(menu,popup->p_wrap,current,&dc);
  335.  
  336.         if (area.valid)
  337.         {
  338.             MouseOff();
  339.             rc_sc_restore(sx,sy,&area,TRUE);
  340.             MouseOn();
  341.         }
  342.         else
  343.             form_dial(FMD_FINISH,0,0,0,0,sx,sy,sw,sh);
  344.  
  345.         _end_ctrl();
  346.         _popup--;
  347.     }
  348.     else
  349.     {
  350.         if (current<0 || current>=menu->ob_tail)
  351.             exit = ob_next(menu,menu->ob_head);
  352.         else
  353.         {
  354.             int temp = ob_next(menu,menu[current].ob_next);
  355.             exit = (temp>0) ? temp : ob_next(menu,menu->ob_head);
  356.         }
  357.     }
  358.  
  359.     if (tree!=NULL && object>0)
  360.         ob_select(info,tree,object,CLEAR_STATE,TRUE);
  361.  
  362.     if (exit>0)
  363.     {
  364.         if (mode & POPUP_CHECK)
  365.         {
  366.             if (current>=0)
  367.                 menu[current].ob_state &= ~CHECKED;
  368.             menu[exit].ob_state |= CHECKED;
  369.         }
  370.  
  371.         if (tree!=NULL && popup->p_set && popup->p_button>0)
  372.         {
  373.             ob_set_text(tree,popup->p_button,ob_get_text(menu,exit,0));
  374.             ob_draw(info,popup->p_button);
  375.             if (popup->p_cycle>0)
  376.                 ob_draw(info,popup->p_cycle);
  377.         }
  378.  
  379.         if (index!=NULL)
  380.         {
  381.             reg int i = 1,radio = 0;
  382.  
  383.             do
  384.             {
  385.                 if ((menu[i].ob_flags & (SELECTABLE|HIDETREE))==SELECTABLE)
  386.                 {
  387.                     if (i==exit)
  388.                     {
  389.                         *index = radio;
  390.                         break;
  391.                     }
  392.                     radio++;
  393.                 }
  394.                 i = menu[i].ob_next;
  395.             } while (i>=0);
  396.         }
  397.     }
  398.  
  399.     _reset_mouse();
  400.  
  401.     if (exit<=0)
  402.         return(0);
  403.     else
  404.         return ((dc) ? (exit|0x8000) : exit);
  405. }
  406.